<template>
  <div class="container">
    <el-card>
      <div class="top">
        <el-select v-model="evaluationType" placeholder="评教类型" size="large">
          <el-option v-for="item in evaluationTypes" :key="item.value" :label="item.label" :value="item.value" />
        </el-select>

        <el-select v-model="factorNum" placeholder="维度个数" size="large">
          <el-option v-for="item in factorNums" :key="item.value" :label="item.label" :value="item.value" />
        </el-select>

        <el-button type="primary" round @click="analysis">开始分析</el-button>
      </div>
    </el-card>

    <div v-show="visible" class="main">
      <!-- kmo检验和Bartlett 的检验 -->
      <div class="kmo content">
        <p class="title">KMO 和 Bartlett 的检验</p>
        <el-table :data="testData" style="width: 100%" border>
          <el-table-column prop="kmo" label="KMO值" align="center" />
          <el-table-column label="Bartlett 球形度检验" align="center">
            <el-table-column prop="statistic" label="统计量" align="center" />
            <el-table-column prop="possibility" label="P值" align="center" />
          </el-table-column>
        </el-table>
        <div class="txt">
          <h3>说明<i class="el-icon-info" style="margin-left: 10px;" /></h3>
          第一：分析KMO值；如果此值高于0.8，则说明非常适合进行因子分析；如果此值介于0.7~0.8之间，则说明比较适合进行因子分析；如果此值介于0.6~0.7，则说明可以进行因子分析；如果此值小于0.6，说明不适合进行因子分析；<br>
          第二：如果Bartlett检验对应p值小于0.05也说明适合进行因子分析；<br>
        </div>
      </div>
      <!-- 方差解释率 -->
      <div class="variance-explain content">
        <p class="title">方差解释率表</p>
        <el-table :data="varianceExplainedList" style="width: 100%" border>
          <el-table-column prop="eigenvalue" label="特征值" align="center" />
          <el-table-column prop="varianceExplained" label="方差解释率" align="center" />
          <el-table-column prop="cumulativeVarianceExplained" label="累计方差解释率" align="center" />
        </el-table>
      </div>
      <!-- 旋转后的方差解释率 -->
      <div class="variance-explain content">
        <p class="title">旋转后方差解释率表</p>
        <el-table :data="rotatedVarianceExplainedList" style="width: 100%" border>
          <el-table-column prop="eigenvalue" label="特征值" align="center" />
          <el-table-column prop="varianceExplained" label="方差解释率" align="center" />
          <el-table-column prop="cumulativeVarianceExplained" label="累计方差解释率" align="center" />
        </el-table>
        <div class="txt">
          <h3>说明<i class="el-icon-info" style="margin-left: 10px;" /></h3>
          方差解释率表格描述总共提取的因子个数；<br>
          特征根：判断因子个数，大于1算做一个因子；<br>
          方差解释率：某个因子能够解释原始变量总方差的比例。方差解释率越高，表明该因子包含原始数据的信息越多。<br>
          <span v-if="rotatedVarianceExplainedList.length !== 0">
            从上表可知：因子分析一共提取出{{ rotatedVarianceExplainedList.length }}个因子，特征根值均大于1，因子旋转后的方差解释率分别是
            <span v-for="(item, idx) in rotatedVarianceExplainedList" :key="idx">{{ item.varianceExplained }}，</span>
            旋转后累积方差解释率为 {{ rotatedVarianceExplainedList[rotatedVarianceExplainedList.length -
              1].cumulativeVarianceExplained }}。
          </span>
        </div>
      </div>
      <!-- 碎石图 -->
      <div class="content">
        <div ref="screePlot" class="chart" />
        <div class="txt">
          <h3>说明<i class="el-icon-info" style="margin-left: 10px;" /></h3>
          碎石图用于辅助判断因子提取个数，当拆线由陡峭突然变得平稳时，陡峭到平稳对应的因子个数即为参考提取因子个数。
        </div>
      </div>
      <!-- 旋转后因子载荷系数表格 -->
      <div class="factor-loading content">
        <p class="title">旋转后因子载荷系数表格</p>
        <el-table :data="factorLoadingList" style="width: 100%" border>
          <el-table-column prop="itemName" label="名称" align="center" />
          <el-table-column
            v-for="(item, idx) in columns"
            :key="idx"
            :prop="item.prop"
            :label="item.label"
            align="center"
          />
          <el-table-column prop="communality" label="共同度" align="center" />
        </el-table>
        <div class="txt">
          <h3>说明<i class="el-icon-info" style="margin-left: 10px;" /></h3>
          通过因子载荷系数值，分析出每个因子与题项的对应关系情况；<br>
          使用最大方差旋转方法（varimax）进行旋转，以便找出因子和研究项的对应关系。<br>
          因子载荷系数：表示因子与分析项之间的关系程度，如果某分析项对应的多个因子载荷系数绝对值均低于0.4，可考虑删除该项；<br>
          共同度：某题项可被提取的信息量，比如0.5,说明50%的信息量被提取，通常以0.4作为标准；
        </div>
      </div>
    </div>

    <div
      v-show="!visible"
      v-loading="loading"
      element-loading-text="拼命加载中"
      element-loading-spinner="el-icon-loading"
      class="loading"
    />
  </div>

</template>

<script>
import { validity } from '@/api/evaluation'
import { Message } from 'element-ui'
import * as echarts from 'echarts'
export default {
  name: 'Validity',
  data() {
    return {
      factorNum: null,
      factorNums: [{
        label: '自动设置',
        value: 0
      }, {
        label: '1',
        value: 1
      }, {
        label: '2',
        value: 2
      }, {
        label: '3',
        value: 3
      }, {
        label: '4',
        value: 4
      }],
      evaluationType: '1',
      evaluationTypes: [{
        label: '学生评教',
        value: '1'
      }, {
        label: '督导评教',
        value: '2'
      }],
      delta: 0,
      // deltas: [0, 0.03, 0.05, 0.1, 0.15],
      testData: [],
      varianceExplainedList: [], // 方差解释率表
      rotatedVarianceExplainedList: [], // 旋转后方差解释率表
      factorLoadingList: [], // 因子载荷
      columns: [], // 因子列
      visible: false, // 是否展示
      loading: false // 是否加载
    }
  },
  methods: {
    analysis() {
      if (this.evaluationType === null || this.factorNum === null) {
        Message({
          message: '请选择参数',
          type: 'warning',
          duration: 2000
        })
        this.visible = false
        return
      }
      this.visible = false // 隐藏
      this.loading = true // 加载
      this.clear()
      validity(this.evaluationType, this.factorNum, this.delta).then(res => {
        // 获取data
        const data = res.data
        if (data === null) {
          Message({
            message: res.message,
            type: 'warning',
            duration: 2000
          })
          this.loading = false
          this.visible = false
          return
        }
        console.log('效度分析：', data)
        // 检验结果：kmo、Bartlett 球形度检验
        const testRes = {}
        testRes.kmo = data.kmo.toFixed(6)
        testRes.statistic = data.statistic.toFixed(6)
        testRes.possibility = data.possibility.toFixed(6)
        this.testData.push(testRes)
        // 方差解释率
        this.savePoints(data.varianceExplainedList)
        this.varianceExplainedList = data.varianceExplainedList
        // 旋转后方差解释率
        this.savePoints(data.rotatedVarianceExplainedList)
        this.rotatedVarianceExplainedList = data.rotatedVarianceExplainedList
        // 碎石图
        const eigenvalues = []
        data.varianceExplainedList.forEach(element => {
          eigenvalues.push(element.eigenvalue)
        })
        this.drawChart(eigenvalues)
        // 因子载荷图
        this.getFactorLoadingList(data.factorLoadingList)
        // 展示
        this.visible = true
        this.loading = false // 关闭加载
      })
    },
    drawChart(data) {
      const xData = []
      for (let index = 0; index < data.length; index++) {
        xData.push(index + 1)
      }
      const chart = echarts.init(this.$refs.screePlot)
      const option = {
        title: {
          text: '碎石图',
          left: 'center'
        },
        tooltip: {
          trigger: 'axis'
        },
        xAxis: {
          type: 'category',
          data: xData
        },
        yAxis: {
          type: 'value'
        },
        series: [
          {
            data: data,
            type: 'line'
          }
        ]
      }
      chart.setOption(option)
    },
    getFactorLoadingList(rawData) {
      // 列信息
      for (let i = 0; i < rawData[0].factorLoadings.length; i++) {
        this.columns.push({ prop: `factor${i + 1}`, label: `因子${i + 1}` })
      }
      // 行信息
      rawData.forEach(element => {
        const row = {}
        row.itemName = element.itemName
        const factorLoadings = element.factorLoadings
        let communality = 1
        for (let i = 0; i < factorLoadings.length; i++) {
          communality *= factorLoadings[i]
          row[`factor${i + 1}`] = factorLoadings[i].toFixed(6)
        }
        row.communality = communality.toFixed(6)
        this.factorLoadingList.push(row)
      })
    },
    savePoints(data) {
      data.forEach(element => {
        element.eigenvalue = element.eigenvalue.toFixed(6)
        element.varianceExplained = element.varianceExplained.toFixed(6)
        element.cumulativeVarianceExplained = element.cumulativeVarianceExplained.toFixed(6)
      })
    },
    clear() {
      this.testData = []
      this.varianceExplainedList = []
      this.factorLoadingList = []
      this.columns = []
    }
  }
}
</script>

<style lang="scss" scoped>
.container {
  padding: 30px;

  .top {
    display: flex;

    .el-select {
      margin-right: 30px;
    }
  }

  .main {
    margin-top: 30px;

    .content {
      margin: 50px 0;

      .txt {
        margin: 30px 0 30px;
        background-color: #F3F9FE;
        padding: 10px;
      }

      .chart {
        margin: 0 auto;
        width: 800px;
        height: 600px;
      }

      .title {
        font-size: 18px;
        font-weight: bold;
        margin: 10px 0;
      }
    }
  }

  .loading {
    height: 70vh;
  }
}
</style>
